/**
 * create by young (young2f@outlook.com) on 2023/6/17
 * mqtt收到设备消息后，通过eventBus发布
 * 同一台设备可能有多个订阅，所以某个退出后不能取消订阅，todo 待优化 removeSubscribe
 */
'use strict';
const _ = require('lodash');
const emq = require('mqtt');
const _stringUtils = require('../utils/stringUtils');
module.exports = class {
  constructor(app) {
    this.app = app;
    this.config = app.config;
    this.mqtt = undefined;
    this.topics = [];
    this.publishCache = [];
  }

  sub(topic) {
    this.topics.push(topic);
    if (this.mqtt && this.mqtt.connected) {
      this.mqtt.subscribe(topic, err => {
        if (err === null || err === undefined) {
          this.app.logger.info('mqtt subscribe ok', topic);
        } else {
          this.app.logger.error('mqtt subscribe error', err);
        }
      });
    }
  }

  removeSub(topic) {
    if (this.mqtt && this.mqtt.connected) {
      this.mqtt.unsubscribe(topic);
    }
  }

  publish(topic, payload) {
    if (this.mqtt && this.mqtt.connected) {
      const opt = {qos: 0, retain: false};
      if (typeof payload === 'object') {
        payload = JSON.stringify(payload);
      }

      this.mqtt.publish(topic, payload, opt, err => {
        if (err) {
          this.app.logger.error('mqtt pub error', topic, err);
        }

      });
      return;
    }
    this.publishCache.push({topic, payload});
  }

  init() {
    if (this.mqtt !== undefined) {
      this.mqtt.end();
      this.mqtt = undefined;
    }
    console.log(this.app.config.iiotConfig)
    const {enable,url, port} = this.app.config.iiotConfig.mqtt;

    this.app.logger.info('正在连接DEVICE MQTT', url, port);
    const qos = 0;
    const opts = {port, qos};
    this.mqtt = emq.connect(url, opts);
    this.mqtt.on('connect', packet => {
      this.app.logger.info('IIOT平台连接成功!!!', url, port);
      /**
       * 通知相关模块，MQTT连接成功
       */
      this.app.eventBus.emit('MQTT_CONNECTED', 'ok');
      /**
       * 加载缓存的订阅
       */
      this.topics.forEach(topic => {
        console.log('订阅topic', topic);
        this.mqtt.subscribe(topic, err => {
          if (err === null || err === undefined) {
            this.app.logger.info('mqtt subscribe ok', topic);
          } else {
            this.app.logger.error('mqtt subscribe error', err);
          }
        });
      });

      /**
       * 发布缓存的发布消息
       * todo 未测试
       */
      this.publishCache.forEach((entity) => {
        const {topic, payload} = entity;
        this.publish(topic, payload);
      });
    });

    /**
     * mqtt订阅消息到达
     */
    this.mqtt.on('message', (topic, message) => {
      console.log('MQTT消息到达', message);
      const json = _stringUtils.buffer2json(message);
      const res = this.app.eventBus.emit(topic, json);
      //console.log('mqtt message emit', topic, res);

    });
    this.mqtt.on('error', error => {
      this.app.logger.error('IIOT平台连接 error', url);
      this.app.eventBus.emit('MQTT_CONNECTED', 'error');
    });
    this.mqtt.on('close', error => {
      this.app.logger.error('IIOT平台连接 close', url);
      this.app.eventBus.emit('MQTT_CONNECTED', 'close');
    });

    this.mqtt.on('offline', error => {
      this.app.logger.error('IIOT平台连接 offline', url);
      this.app.eventBus.emit('MQTT_CONNECTED', 'offline');
    });
    return Promise.resolve('');
  }
};
